﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using FC.GEPluginCtrls.Geo;
using System.Runtime.InteropServices;
using System.IO;
using FC.GEPluginCtrls.Geo;

namespace VehicleTrajectoryApp
{
    public partial class SQLiteFiletoBinaryForm : Form
    {
        private string inputSQLiteDBFileName = string.Empty;
        private string coordinateMappingFileName = string.Empty;
        private string inputNodeFileName = string.Empty;
        private string outputBinFileName = string.Empty;

        private string commandString = string.Empty;

        // added by Hongkai Yu, 12/4/2012
        struct TAZ_Data
        {
            public Coordinate coordinate;
            public int TAZ_zone_id;
        };
        struct Aimsun_Data
        {
            public int oid;
            public int sectionId;
            public double xCoord;
            public double yCoord;
            public double timeSta;
        };
        public class IniFile
        {
            public string path;

            [DllImport("kernel32")]
            private static extern long WritePrivateProfileString(string section,
                string key, string val, string filePath);
            [DllImport("kernel32")]
            private static extern int GetPrivateProfileString(string section,
                     string key, string def, StringBuilder retVal,
                int size, string filePath);

            /// <summary>
            /// INIFile Constructor.
            /// </summary>
            /// <PARAM name="INIPath"></PARAM>
            public IniFile(string INIPath)
            {
                path = INIPath;
            }
            /// <summary>
            /// Write Data to the INI File
            /// </summary>
            /// <PARAM name="Section"></PARAM>
            /// Section name
            /// <PARAM name="Key"></PARAM>
            /// Key Name
            /// <PARAM name="Value"></PARAM>
            /// Value Name
            public void IniWriteValue(string Section, string Key, string Value)
            {
                WritePrivateProfileString(Section, Key, Value, this.path);
            }

            /// <summary>
            /// Read Data Value From the Ini File
            /// </summary>
            /// <PARAM name="Section"></PARAM>
            /// <PARAM name="Key"></PARAM>
            /// <PARAM name="Path"></PARAM>
            /// <returns></returns>
            public string IniReadValue(string Section, string Key)
            {
                StringBuilder temp = new StringBuilder(255);
                int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
                return temp.ToString();
            }
        }

        public SQLiteFiletoBinaryForm()
        {
            InitializeComponent();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.Filter = "SQLite DB File|*.sqlite|All Files |*.*";
            if (this.openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                inputSQLiteDBFileName = openFileDialog1.FileName;
                textBox1.Text = inputSQLiteDBFileName;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.Filter = "Binary File|*.bin";
            if (this.saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                outputBinFileName = saveFileDialog1.FileName;
                textBox2.Text = outputBinFileName;
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (inputSQLiteDBFileName.Length > 0 && outputBinFileName.Length > 0                
                && File.Exists(inputSQLiteDBFileName) && File.Exists(coordinateMappingFileName))
            {
                string csvFileName = Application.StartupPath + "\\exported.csv";
                if (ConvertSQLiteDBFileToCSV(inputSQLiteDBFileName, System.IO.Path.GetFileName(csvFileName)))
                {
                    int numOfVehicles = ConvertCSVToBinary(csvFileName, coordinateMappingFileName, inputNodeFileName, outputBinFileName);
                    //added by Hongkai Yu, 12/4/2012
                    if (numOfVehicles < 0)
                    {
                        MessageBox.Show("NO vehicle loaded!");
                    }
                    else
                    {
                        MessageBox.Show(String.Format("{0} vehicles are extracted from SQLite database file!", numOfVehicles));
                    }
                }
            }
        }

        private bool ConvertSQLiteDBFileToCSV(string sqliteDBFile, string csvFileName)
        {
            string exePath = Application.StartupPath;

            commandString = ".mode csv\n";
            commandString += ".separator \",\"\n";
            commandString += ".output ";
            commandString += csvFileName + "\n";
            commandString += ".header on\n";
            commandString += "select oid, sectionId, xCoord, yCoord, timeSta from MIVEHDETAILEDTRAJECTORY;";

            using (StreamWriter writer = new StreamWriter(exePath + "\\command.txt"))
            {
                writer.Write(commandString);
            }

            if (File.Exists(exePath + "\\sqlite3.exe"))
            {
                using (StreamWriter writer = new StreamWriter(exePath + "\\sqlite.bat"))
                {
                    writer.WriteLine("\"" + exePath + "\\sqlite3.exe\" " + "\"" + sqliteDBFile + "\"" + " < command.txt");
                }

                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo.FileName = "\"" + exePath + "\\sqlite.bat" + "\"";
                //proc.StartInfo.RedirectStandardOutput = true;
                //proc.StartInfo.RedirectStandardError = true;
                //proc.StartInfo.UseShellExecute = false;

                proc.Start();
                proc.WaitForExit();
                //string result = proc.StandardOutput.ReadToEnd();
                //result += proc.StandardError.ReadToEnd();
                //MessageBox.Show(result);
            }
            return true;
        }

        private int ConvertCSVToBinary(string csv_path, string ini_path, string input_node_path, string output_bin_path)
        {
            int vehicle_num = -1;//value to be returned 

            //INPUT
            //parameters for changing coordinate system
            double Original_Point1_x = -1;
            double Original_Point1_y = -1;
            double Original_Point2_x = -1;
            double Original_Point2_y = -1;
            double Changed_Point1_x = -1;
            double Changed_Point1_y = -1;
            double Changed_Point2_x = -1;
            double Changed_Point2_y = -1;

            // build the map to match the node id to TAZ zone id
            Dictionary<int, TAZ_Data> node_to_Zone_Map = new Dictionary<int, TAZ_Data>();
            using (StreamReader reader = new StreamReader(input_node_path))
            {
                string line;
                line = reader.ReadLine();
                while ((line = reader.ReadLine()) != null)
                {
                    TAZ_Data taz_data;
                    string[] subString = line.Split(',');
                    int node_id = Int32.Parse(subString[0]);
                    double lon = Double.Parse(subString[1]);
                    double lat = Double.Parse(subString[2]);
                    taz_data.TAZ_zone_id = Int32.Parse(subString[3]);
                    Coordinate coordinate = new Coordinate(lon, lat);
                    taz_data.coordinate = coordinate;
                    node_to_Zone_Map[node_id] = taz_data;
                }
            }
            IniFile iniFile = new IniFile(ini_path);
            string o_p1_x = iniFile.IniReadValue("Settings", "Original_Point1_x");
            string o_p1_y = iniFile.IniReadValue("Settings", "Original_Point1_y");
            string o_p2_x = iniFile.IniReadValue("Settings", "Original_Point2_x");
            string o_p2_y = iniFile.IniReadValue("Settings", "Original_Point2_y");
            string c_p1_x = iniFile.IniReadValue("Settings", "Changed_Point1_x");
            string c_p1_y = iniFile.IniReadValue("Settings", "Changed_Point1_y");
            string c_p2_x = iniFile.IniReadValue("Settings", "Changed_Point2_x");
            string c_p2_y = iniFile.IniReadValue("Settings", "Changed_Point2_y");
            Original_Point1_x = Double.Parse(o_p1_x);
            Original_Point1_y = Double.Parse(o_p1_y);
            Original_Point2_x = Double.Parse(o_p2_x);
            Original_Point2_y = Double.Parse(o_p2_y);
            Changed_Point1_x = Double.Parse(c_p1_x);
            Changed_Point1_y = Double.Parse(c_p1_y);
            Changed_Point2_x = Double.Parse(c_p2_x);
            Changed_Point2_y = Double.Parse(c_p2_y);
            Changecoordinates change_cordinate = new Changecoordinates(Original_Point1_x, Original_Point1_y, Original_Point2_x, Original_Point2_y, Changed_Point1_x, Changed_Point1_y, Changed_Point2_x, Changed_Point2_y);

            //OPERATION
            List<GPS_Binary_Data> GPS_Binary_Data_List;//a list to record GPS binary data
            GPS_Binary_Data_List = new List<GPS_Binary_Data>();
            GPS_Binary_Data_List.Clear();
            string output_filename = output_bin_path;//The File we output after data file fusion 
            BinaryWriter binWriter = new BinaryWriter(File.Open(output_filename, FileMode.Create));
            int date_id = 18;//July 18th
            int original_tomtom_vehicle_id = 8888;//we put 8888 to define non-sensitive value, 
            double departure_time_in_min = 0;
            double arrival_time_in_min = 0;
            double trip_time_in_min;
            int num_of_nodes = 0;
            // get the max gps point id for one vehicle id
            int current_vehicle_id = -1;
            int former_vehicle_id = -1;
            // each segment has two nodes. we give 0 to the first node, and give segment distance in km to the second node 
            List<float> GPS_Node_Information_List;// x,y,time, segment distance
            GPS_Node_Information_List = new List<float>();
            double origin_x = 0;
            double origin_y = 0;
            double destination_x = 0;
            double destination_y = 0;
            GPSpoint origin_point;
            GPSpoint destination_point;
            int origin_zone_id = -1, dest_zone_id = -1;            //(TAZ zone id after matching)

            double Point_to_Point_Distance = 0;
            double section_start_point_x = -1;
            double section_start_point_y = -1;
            double section_end_point_x = -1;
            double section_end_point_y = -1;
            int section_id = -1;
            float section_start_time = -1;
            float section_end_time = -1;
            double xCoord = -1;
            double yCoord = -1;
            double timeSta = -1;


            StreamReader csv_file = new StreamReader(csv_path);
            string Line = csv_file.ReadLine(); //read the table head first


            List<Aimsun_Data> Aimsun_Data_List;//a list to record GPS binary data
            Aimsun_Data_List = new List<Aimsun_Data>();

            while ((Line = csv_file.ReadLine()) != null) //read every line
            {
                Aimsun_Data aimsun_data;
                string[] subString = Line.Split(',');//split the string
                if (current_vehicle_id == -1)
                {
                    current_vehicle_id = int.Parse(subString[0]);
                    section_id = int.Parse(subString[1]);
                    xCoord = double.Parse(subString[2]);
                    yCoord = double.Parse(subString[3]);
                    timeSta = double.Parse(subString[4]);
                    aimsun_data.oid = current_vehicle_id;
                    aimsun_data.sectionId = section_id;
                    aimsun_data.xCoord = xCoord;
                    aimsun_data.yCoord = yCoord;
                    aimsun_data.timeSta = timeSta;
                    Aimsun_Data_List.Add(aimsun_data);
                }
                current_vehicle_id = int.Parse(subString[0]);
                if (current_vehicle_id != former_vehicle_id)
                {
                    //deal with the Aimsun_Data_List because the information of last vehicle is stored in the Aimsun_Data_List
                    for (int i = 0; i < Aimsun_Data_List.Count; i++)
                    {
                        if (i == 0)//origin point
                        {
                            //num_of_nodes = num_of_nodes + 1;
                            departure_time_in_min = Aimsun_Data_List[i].timeSta / 60;
                            origin_x = Aimsun_Data_List[i].xCoord;
                            origin_y = Aimsun_Data_List[i].yCoord;
                            origin_point = change_cordinate.ChangeCoordinatesSystem(origin_x, origin_y);
                            origin_x = origin_point.x;
                            origin_y = origin_point.y;
                            Point_to_Point_Distance = 0;

                            //previous_point_x = origin_x;
                            //previous_point_y = origin_y;
                            section_start_point_x = origin_x;
                            section_start_point_y = origin_y;
                            section_id = Aimsun_Data_List[i].sectionId;
                            section_start_time = (float)Aimsun_Data_List[i].timeSta / 60;

                            //x,y,time stamp for each GPS point
                            GPS_Node_Information_List.Add((float)(origin_x));
                            GPS_Node_Information_List.Add((float)(origin_y));
                            GPS_Node_Information_List.Add(section_start_time);
                            GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the first point
                        }
                        else if (i == (Aimsun_Data_List.Count - 1))//destination point
                        {
                            arrival_time_in_min = Aimsun_Data_List[i].timeSta / 60;
                            destination_x = Aimsun_Data_List[i].xCoord;
                            destination_y = Aimsun_Data_List[i].yCoord;
                            destination_point = change_cordinate.ChangeCoordinatesSystem(destination_x, destination_y);
                            destination_x = destination_point.x;
                            destination_y = destination_point.y;

                            section_end_point_x = destination_x;
                            section_end_point_y = destination_y;

                            //calculate the segment distance, return value : km
                            //Coordinate StartPoint = new Coordinate(previous_point_x, previous_point_y);
                            //Coordinate EndPoint = new Coordinate(current_point_x, current_point_y);
                            Coordinate StartPoint = new Coordinate(section_start_point_x, section_start_point_y);
                            Coordinate EndPoint = new Coordinate(section_end_point_x, section_end_point_y);
                            Point_to_Point_Distance = Maths.DistanceCosine(StartPoint, EndPoint);

                            section_end_time = (float)Aimsun_Data_List[i].timeSta / 60;
                            //x,y,time stamp,distance for each GPS point
                            GPS_Node_Information_List.Add((float)(destination_x));
                            GPS_Node_Information_List.Add((float)(destination_y));
                            GPS_Node_Information_List.Add(section_end_time);
                            GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));

                            //TAZ zone id calculation
                            Coordinate startCoordinate = new Coordinate(origin_x, origin_y);
                            Coordinate endCoordinate = new Coordinate(destination_x, destination_y);
                            double d1 = Double.MaxValue, d2 = Double.MaxValue;
                            foreach (int node_id in node_to_Zone_Map.Keys)
                            {
                                Coordinate coordinate = node_to_Zone_Map[node_id].coordinate;
                                double distance = Maths.DistanceCosine(startCoordinate, coordinate);
                                if (d1 > distance)
                                {
                                    d1 = distance;
                                    origin_zone_id = node_to_Zone_Map[node_id].TAZ_zone_id;
                                }
                                distance = Maths.DistanceCosine(endCoordinate, coordinate);
                                if (d2 > distance)
                                {
                                    d2 = distance;
                                    dest_zone_id = node_to_Zone_Map[node_id].TAZ_zone_id;
                                }
                            }
                            num_of_nodes = 2 * num_of_nodes;
                            trip_time_in_min = arrival_time_in_min - departure_time_in_min;
                            float total_distance_in_km = 0;
                            for (int j = 3; j < GPS_Node_Information_List.Count; j = j + 4)
                            {
                                total_distance_in_km = total_distance_in_km + GPS_Node_Information_List[j];
                            }
                            num_of_nodes = GPS_Node_Information_List.Count / 4;
                            float reserved_field1 = 8888;
                            float reserved_field2 = 8888;
                            float reserved_field3 = 8888;
                            GPS_Binary_Data gps_binary_data = new GPS_Binary_Data(original_tomtom_vehicle_id, date_id, Aimsun_Data_List[i].oid, origin_zone_id, dest_zone_id, (float)departure_time_in_min, (float)arrival_time_in_min, (float)trip_time_in_min, total_distance_in_km, num_of_nodes, reserved_field1, reserved_field2, reserved_field3, GPS_Node_Information_List);
                            GPS_Binary_Data_List.Add(gps_binary_data);
                            GPS_Node_Information_List = new List<float>();
                            GPS_Node_Information_List.Clear();
                            origin_x = 0;
                            origin_y = 0;
                            destination_x = 0;
                            destination_y = 0;
                            origin_zone_id = -1;
                            dest_zone_id = -1;            //(zone id after matching)
                            Point_to_Point_Distance = 0;
                            section_start_point_x = -1;
                            section_start_point_y = -1;
                            section_end_point_x = -1;
                            section_end_point_y = -1;
                            section_start_time = -1;
                            section_end_time = -1;
                            section_id = -1;
                            num_of_nodes = 0;
                            current_vehicle_id = -1;
                            Aimsun_Data_List = new List<Aimsun_Data>();
                            Aimsun_Data_List.Clear();
                        }
                        else
                        {
                            if (Aimsun_Data_List[i].sectionId == section_id)
                            {
                                section_end_point_x = Aimsun_Data_List[i].xCoord;
                                section_end_point_y = Aimsun_Data_List[i].yCoord;
                                GPSpoint section_end_point;
                                section_end_point = change_cordinate.ChangeCoordinatesSystem(section_end_point_x, section_end_point_y);
                                section_end_point_x = section_end_point.x;
                                section_end_point_y = section_end_point.y;
                                section_end_time = (float)Aimsun_Data_List[i].timeSta / 60;
                            }
                            else
                            {

                                //num_of_nodes = num_of_nodes + 1;
                                //old section id has been changed, save the data for section end point
                                //calculate the segment distance, return value : km
                                Coordinate StartPoint = new Coordinate(section_start_point_x, section_start_point_y);
                                Coordinate EndPoint = new Coordinate(section_end_point_x, section_end_point_y);
                                Point_to_Point_Distance = Maths.DistanceCosine(StartPoint, EndPoint);// distance between the section start point to section end point for the same section
                                //x,y,time stamp,distance for the section end point
                                GPS_Node_Information_List.Add((float)(section_end_point_x));
                                GPS_Node_Information_List.Add((float)(section_end_point_y));
                                GPS_Node_Information_List.Add(section_end_time);
                                GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the first point

                                //new section id starts

                                section_start_point_x = Aimsun_Data_List[i].xCoord;
                                section_start_point_y = Aimsun_Data_List[i].yCoord;
                                GPSpoint section_start_point;
                                section_start_point = change_cordinate.ChangeCoordinatesSystem(section_start_point_x, section_start_point_y);
                                section_start_point_x = section_start_point.x;
                                section_start_point_y = section_start_point.y;
                                section_id = Aimsun_Data_List[i].sectionId;
                                section_start_time = (float)Aimsun_Data_List[i].timeSta;

                                Coordinate StartPoint2 = new Coordinate(section_start_point_x, section_start_point_y);
                                Coordinate EndPoint2 = new Coordinate(section_end_point_x, section_end_point_y);
                                Point_to_Point_Distance = Maths.DistanceCosine(StartPoint2, EndPoint2);// distance between the section start point of (i+1)th section to section end point of ith section

                                //x,y,time stamp for each GPS point
                                GPS_Node_Information_List.Add((float)(section_start_point_x));
                                GPS_Node_Information_List.Add((float)(section_start_point_y));
                                GPS_Node_Information_List.Add(section_start_time);
                                GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the section start point

                            }
                        }
                    }
                }
                else
                {
                    current_vehicle_id = int.Parse(subString[0]);
                    section_id = int.Parse(subString[1]);
                    xCoord = double.Parse(subString[2]);
                    yCoord = double.Parse(subString[3]);
                    timeSta = double.Parse(subString[4]);
                    aimsun_data.oid = current_vehicle_id;
                    aimsun_data.sectionId = section_id;
                    aimsun_data.xCoord = xCoord;
                    aimsun_data.yCoord = yCoord;
                    aimsun_data.timeSta = timeSta;
                    Aimsun_Data_List.Add(aimsun_data);
                }
                former_vehicle_id = current_vehicle_id;
            }
            // FOR THE LAST VEHICLE, because its vehicle id cannot be changed
            if (Aimsun_Data_List.Count != 0)
            {
                for (int i = 0; i < Aimsun_Data_List.Count; i++)
                {
                    if (i == 0)//origin point
                    {
                       // num_of_nodes = num_of_nodes + 1;
                        departure_time_in_min = Aimsun_Data_List[i].timeSta / 60;
                        origin_x = Aimsun_Data_List[i].xCoord;
                        origin_y = Aimsun_Data_List[i].yCoord;
                        origin_point = change_cordinate.ChangeCoordinatesSystem(origin_x, origin_y);
                        origin_x = origin_point.x;
                        origin_y = origin_point.y;
                        Point_to_Point_Distance = 0;

                        //previous_point_x = origin_x;
                        //previous_point_y = origin_y;
                        section_start_point_x = origin_x;
                        section_start_point_y = origin_y;
                        section_id = Aimsun_Data_List[i].sectionId;
                        section_start_time = (float)Aimsun_Data_List[i].timeSta / 60;

                        //x,y,time stamp for each GPS point
                        GPS_Node_Information_List.Add((float)(origin_x));
                        GPS_Node_Information_List.Add((float)(origin_y));
                        GPS_Node_Information_List.Add(section_start_time);
                        GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the first point
                    }
                    else if (i == (Aimsun_Data_List.Count - 1))//destination point
                    {
                        arrival_time_in_min = Aimsun_Data_List[i].timeSta / 60;
                        destination_x = Aimsun_Data_List[i].xCoord;
                        destination_y = Aimsun_Data_List[i].yCoord;
                        destination_point = change_cordinate.ChangeCoordinatesSystem(destination_x, destination_y);
                        destination_x = destination_point.x;
                        destination_y = destination_point.y;

                        section_end_point_x = destination_x;
                        section_end_point_y = destination_y;

                        //calculate the segment distance, return value : km
                        //Coordinate StartPoint = new Coordinate(previous_point_x, previous_point_y);
                        //Coordinate EndPoint = new Coordinate(current_point_x, current_point_y);
                        Coordinate StartPoint = new Coordinate(section_start_point_x, section_start_point_y);
                        Coordinate EndPoint = new Coordinate(section_end_point_x, section_end_point_y);
                        Point_to_Point_Distance = Maths.DistanceCosine(StartPoint, EndPoint);

                        section_end_time = (float)Aimsun_Data_List[i].timeSta / 60;
                        //x,y,time stamp,distance for each GPS point
                        GPS_Node_Information_List.Add((float)(destination_x));
                        GPS_Node_Information_List.Add((float)(destination_y));
                        GPS_Node_Information_List.Add(section_end_time);
                        GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));

                        //TAZ zone id calculation
                        Coordinate startCoordinate = new Coordinate(origin_x, origin_y);
                        Coordinate endCoordinate = new Coordinate(destination_x, destination_y);
                        double d1 = Double.MaxValue, d2 = Double.MaxValue;
                        foreach (int node_id in node_to_Zone_Map.Keys)
                        {
                            Coordinate coordinate = node_to_Zone_Map[node_id].coordinate;
                            double distance = Maths.DistanceCosine(startCoordinate, coordinate);
                            if (d1 > distance)
                            {
                                d1 = distance;
                                origin_zone_id = node_to_Zone_Map[node_id].TAZ_zone_id;
                            }
                            distance = Maths.DistanceCosine(endCoordinate, coordinate);
                            if (d2 > distance)
                            {
                                d2 = distance;
                                dest_zone_id = node_to_Zone_Map[node_id].TAZ_zone_id;
                            }
                        }
                        num_of_nodes = 2 * num_of_nodes;
                        trip_time_in_min = arrival_time_in_min - departure_time_in_min;
                        float total_distance_in_km = 0;
                        for (int j = 3; j < GPS_Node_Information_List.Count; j = j + 4)
                        {
                            total_distance_in_km = total_distance_in_km + GPS_Node_Information_List[j];
                        }
                        num_of_nodes = GPS_Node_Information_List.Count / 4;
                        float reserved_field1 = 8888;
                        float reserved_field2 = 8888;
                        float reserved_field3 = 8888;
                        GPS_Binary_Data gps_binary_data = new GPS_Binary_Data(original_tomtom_vehicle_id, date_id, Aimsun_Data_List[i].oid, origin_zone_id, dest_zone_id, (float)departure_time_in_min, (float)arrival_time_in_min, (float)trip_time_in_min, total_distance_in_km, num_of_nodes, reserved_field1, reserved_field2, reserved_field3, GPS_Node_Information_List);
                        GPS_Binary_Data_List.Add(gps_binary_data);
                        GPS_Node_Information_List = new List<float>();
                        GPS_Node_Information_List.Clear();
                        origin_x = 0;
                        origin_y = 0;
                        destination_x = 0;
                        destination_y = 0;
                        origin_zone_id = -1;
                        dest_zone_id = -1;            //(zone id after matching)
                        Point_to_Point_Distance = 0;
                        section_start_point_x = -1;
                        section_start_point_y = -1;
                        section_end_point_x = -1;
                        section_end_point_y = -1;
                        section_start_time = -1;
                        section_end_time = -1;
                        section_id = -1;
                        num_of_nodes = 0;
                        current_vehicle_id = -1;
                        Aimsun_Data_List = new List<Aimsun_Data>();
                        Aimsun_Data_List.Clear();
                    }
                    else
                    {
                        if (Aimsun_Data_List[i].sectionId == section_id)
                        {
                            section_end_point_x = Aimsun_Data_List[i].xCoord;
                            section_end_point_y = Aimsun_Data_List[i].yCoord;
                            GPSpoint section_end_point;
                            section_end_point = change_cordinate.ChangeCoordinatesSystem(section_end_point_x, section_end_point_y);
                            section_end_point_x = section_end_point.x;
                            section_end_point_y = section_end_point.y;
                            section_end_time = (float)Aimsun_Data_List[i].timeSta / 60;
                        }
                        else
                        {

                            num_of_nodes = num_of_nodes + 1;
                            //old section id has been changed, save the data for section end point
                            //calculate the segment distance, return value : km
                            Coordinate StartPoint = new Coordinate(section_start_point_x, section_start_point_y);
                            Coordinate EndPoint = new Coordinate(section_end_point_x, section_end_point_y);
                            Point_to_Point_Distance = Maths.DistanceCosine(StartPoint, EndPoint);// distance between the section start point to section end point for the same section
                            //x,y,time stamp,distance for the section end point
                            GPS_Node_Information_List.Add((float)(section_end_point_x));
                            GPS_Node_Information_List.Add((float)(section_end_point_y));
                            GPS_Node_Information_List.Add(section_end_time);
                            GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the first point

                            //new section id starts

                            section_start_point_x = Aimsun_Data_List[i].xCoord;
                            section_start_point_y = Aimsun_Data_List[i].yCoord;
                            GPSpoint section_start_point;
                            section_start_point = change_cordinate.ChangeCoordinatesSystem(section_start_point_x, section_start_point_y);
                            section_start_point_x = section_start_point.x;
                            section_start_point_y = section_start_point.y;
                            section_id = Aimsun_Data_List[i].sectionId;
                            section_start_time = (float)Aimsun_Data_List[i].timeSta;

                            Coordinate StartPoint2 = new Coordinate(section_start_point_x, section_start_point_y);
                            Coordinate EndPoint2 = new Coordinate(section_end_point_x, section_end_point_y);
                            Point_to_Point_Distance = Maths.DistanceCosine(StartPoint2, EndPoint2);// distance between the section start point of (i+1)th section to section end point of ith section

                            //x,y,time stamp for each GPS point
                            GPS_Node_Information_List.Add((float)(section_start_point_x));
                            GPS_Node_Information_List.Add((float)(section_start_point_y));
                            GPS_Node_Information_List.Add(section_start_time);
                            GPS_Node_Information_List.Add((float)(Point_to_Point_Distance));// 0 distance for the section start point

                        }
                    }
                }
            }
            // output Binary file
            for (int i = 0; i < GPS_Binary_Data_List.Count; i++)
            {
                binWriter.Write(GPS_Binary_Data_List[i].original_tomtom_vehicle_id);
                binWriter.Write(GPS_Binary_Data_List[i].date_id);
                binWriter.Write(GPS_Binary_Data_List[i].vehicle_id);
                binWriter.Write(GPS_Binary_Data_List[i].origin_zone_id);
                binWriter.Write(GPS_Binary_Data_List[i].dest_zone_id);
                binWriter.Write(GPS_Binary_Data_List[i].departure_time_in_min);
                binWriter.Write(GPS_Binary_Data_List[i].arrival_time_in_min);
                binWriter.Write(GPS_Binary_Data_List[i].trip_time_in_min);
                binWriter.Write(GPS_Binary_Data_List[i].total_distance_in_km);
                binWriter.Write(GPS_Binary_Data_List[i].num_of_nodes);
                binWriter.Write(GPS_Binary_Data_List[i].reserved_field1);
                binWriter.Write(GPS_Binary_Data_List[i].reserved_field2);
                binWriter.Write(GPS_Binary_Data_List[i].reserved_field3);

                for (int j = 0; j < GPS_Binary_Data_List[i].GPS_Node_Information_List.Count; j++)
                {
                    binWriter.Write(GPS_Binary_Data_List[i].GPS_Node_Information_List[j]); //x,y,time,segment distance in km
                }
            }
            binWriter.Close();
            vehicle_num = GPS_Binary_Data_List.Count;

            if (vehicle_num > 0)//right
            {
                return vehicle_num;
            }
            else
            {
                return (-1);// wrong 
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.Filter = "Coordinate Mapping File|*.ini";
            if (this.openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                coordinateMappingFileName = openFileDialog1.FileName;
                this.textBox3.Text = coordinateMappingFileName;
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.Filter = "Input Node File|*.csv|All Files|*.*";
            if (this.openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                inputNodeFileName = openFileDialog1.FileName;
                this.textBox4.Text = inputNodeFileName;
            }
        }
    }
}
